package chat

import (
	"bigmodel/service/chat/aliyun"
	"context"
	"encoding/json"
	"errors"
	"net/http"

	"github.com/swxctx/xlog"
)

type AliYun struct {
	cli *aliyun.Client
}

func NewAliYun(apiKey string,debug ...bool)(*AliYun){
	ali := &AliYun{
		cli: aliyun.MustNewClient(apiKey,debug...),
	}
	return ali
}

func MustNewAliYun(apiKey string,debug ...bool)(*AliYun){
	ali := NewAliYun(apiKey,debug...)
	return ali
}

func (ali *AliYun)Chat(ctx context.Context, resw http.ResponseWriter, args *ChatDoArgsV1,conf string) (*ChatDoResultV1, error){
	param := &aliyun.Parameters{}
	err := json.Unmarshal([]byte(conf),param)
	if err != nil{
		return nil,errors.New(err.Error())
	}
	if param.Temperature == 0.0 {
		param.Temperature = 0.7
	}
	if param.MaxTokens == 0 {
		param.MaxTokens = 1024
	}
	param.ResultFormat = aliyun.RESULT_FORMAT_MESSAGE
	
	if !contains(aliyun.MODEL_ARR[:],args.Model) {
		return nil,errors.New("未知的模型名称")
	}
	req := &aliyun.ChatRequest{
		Model: args.Model,
		Input: aliyun.Input{
			Prompt: args.Content,
		},
		Parameters: *param,
	}
	if !args.Stream {
		resp,err := ali.cli.Chat(req)
		if err != nil {
			return nil,err
		}
		return &ChatDoResultV1{
			Message: resp.Output.Choices[0].Message.Content,
		},nil
	}else{
		param.IncrementalOutput = true
		streamReader,err := ali.cli.ChatStream(req)
		if err != nil {
			return nil,errors.New(err.Error())
		}
		defer streamReader.Close()
		f,ok := resw.(http.Flusher)
		if !ok {
			return nil,errors.New(err.Error())
		}
		for {
			data, err := streamReader.ReceiveFormat()
			if err != nil {
				xlog.Errorf("err-> %v", err)
				break
			}
			if streamReader.IsFinish() {
				xlog.Infof("read finish...")
				break
			}
			if streamReader.IsMaxEmptyLimit() {
				xlog.Errorf("read empty limit...")
				break
			}
			if data != nil {
				resw.Write(streamResponse(data.Output.Choices[0].Message.Content))
				f.Flush()
			}
		}
	}
	return &ChatDoResultV1{
		Message: aliyun.RESULT_FORMAT_MESSAGE,
	},nil
}

func params()(*aliyun.Parameters){
	return &aliyun.Parameters{
		MaxTokens: 1024,
		Temperature: 0.7,
		ResultFormat: aliyun.RESULT_FORMAT_MESSAGE,
	}
}

func contains(slice []string, val string) bool {  
    for _, item := range slice {  
        if item == val {  
            return true  
        }  
    }  
    return false  
} 